#include <iostream>
#include <typeinfo>
#include <cassert>
#include <vector>
#include <string>
#include <algorithm>

using std::string;
using std::cout;
using std::endl;
//为什么要clone？ 
//--> 对于赋值运算符重载，构建出来的临时Any对象中的_content在使用前就会被delete
//--> 对于拷贝构造，为了完成深拷贝
class Any
{
public:
    Any():_content(nullptr){}

    template<class T>
    Any(const T& val)
    :_content(new placeholders<T>(val))      //用子类的指针初始化父类的指针
    {}

    Any(const Any& any)
    :_content(any._content == nullptr ? nullptr : (any._content->clone()))      //指针使用注意要判空！
    {}

    Any& swap(Any any)       //交换地址，让临时变量把老地址“带走”       //由于要交换临时变量（常性），故无法传引用了
    {
        std::swap(_content, any._content);
        return *this;
    }

    template<class T>
    Any& operator=(const T& val)    
    {
        // if(_content)
        // {
        //     delete _content;
        // }
        // _content = Any(val)._content->clone();

        swap(Any(val));
        return *this;
    }    

    Any& operator=(Any& any)
    {
        // if(_content)
        // {
        //     delete _content;
        // }
        // _content = any._content;
        swap(any);
        return *this;
    }

    ~Any()
    {
        if(_content != nullptr)
        delete _content;
    }

    template<class T>
    T* Get()    
    {
        assert(typeid(T) == _content->type());
        return &(((placeholders<T>*)(_content)) ->_val);
    }

    class holders
    {
    public:
        virtual const std::type_info& type(){}    //主要用于类型判断而不是类型使用
        virtual holders* clone(){}     //注意是子类指针 不是子类的类型的指针！！
        virtual ~holders(){}
    };

    template<class T>
    class placeholders : public holders
    {
    public:
        placeholders(T val)
        :_val(val)
        {}

        const std::type_info& type(){return typeid(T);}

        holders* clone()
        {
            return (new placeholders<T>(_val));
        }

    public:
        T _val;
    };

private:
    holders* _content;
};

int main()
{
    Any a(10);
    int* pi = a.Get<int>();
    cout << *pi << endl;

    a = string("hello");
    string* pa = a.Get<string>();
    cout << *pa << endl;

    Any b(a);
    string* pb = b.Get<string>();
    cout << *pb << endl;

    Any c = std::vector<int>{1,2,3};
    b = c;
    std::vector<int>* pc = b.Get<std::vector<int>>();
    for(int i = 0; i < pc->size(); i++)
    {
        cout << (*pc)[i] << " ";
    }
    cout << endl;

    return 0;
}